package middleman;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import messages.Message;
import messages.plain.TextMessage;
import utils.ConstantVariables;

/**
 * Mallory listens to 127.0.0.1:12345.
 * 
 * Mallory has two threads. One of them intercepts messages from Alice to Bob
 * and the other one intercepts messages from Bob to Alice.
 * 
 * It acts like a server. Alice and Bob connect to mallory upon start.
 * 
 * ALL THE '1's STANDS FOR CONNECTIONS WITH ALICE. ALICE SHOULD CONNECT FIRST.
 * 
 * 
 * 
 * @author bh349
 * 
 */
public class Mallory
{

    /**
     * @param args
     * @throws IOException
     */
    MalloryThread thread1;

    MalloryThread thread2;

    Socket inComingSocket1;

    Socket inComingSocket2;

    Socket outGoingSocket1;

    Socket outGoingSocket2;

    ObjectOutputStream out1;

    ObjectOutputStream out2;

    public static void main( String[] args ) throws IOException {
        System.out.println( "This is Mallory." );
        Mallory mallory = new Mallory();
        mallory.run();
    }

    private void run() throws IOException {
        ServerSocket serverSocket = new ServerSocket(
                ConstantVariables.MALLORY_PORT );
        while( true ) {
            if( inComingSocket1 == null ) {
                inComingSocket1 = serverSocket.accept();
                System.out
                        .println( "listening to incoming messages from Alice" );
            } else if( inComingSocket2 == null ) {
                inComingSocket2 = serverSocket.accept();
                System.out.println( "listening to incoming messages from Bob" );
            }
            if( thread1 == null ) {
                thread1 = new MalloryThread( this, inComingSocket1, 1 );
                thread1.start();
            } else if( thread2 == null ) {
                thread2 = new MalloryThread( this, inComingSocket2, 2 );
                thread2.start();
            }
        }
    }

    /**
     * Whenever Mallory receives a message, call this to ask if Mallory wants to
     * change it.
     * 
     * @param msg
     * @return
     * @throws IOException
     */
    public Message changeMessage( Message msg ) throws IOException {
        msg.show();
        System.out.println( "Change the message?(Y/N)" );
        if( "Y".equalsIgnoreCase( new BufferedReader( new InputStreamReader(
                System.in ) ).readLine() ) ) {
            // change message content to MMMMMMMMMMMMMM
            TextMessage text = new TextMessage(
                    "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM" );
            return text;
        }
        return msg;
    }

    /**
     * Forward the message. If from Alice, forward to Bob. Otherwise Forward to
     * Alice.
     * 
     * @param msg
     * @param fromAlice
     * @throws IOException
     */
    public void forwardMessage( Message msg, int threadId ) throws IOException {
        if( threadId == 1 ) {
            if( outGoingSocket2 == null ) {
                outGoingSocket2 = new Socket( ConstantVariables.IP,
                        ConstantVariables.BOB_PORT );
                out2 = new ObjectOutputStream(
                        outGoingSocket2.getOutputStream() );
            }
            out2.writeObject( msg );
            System.out.println( "Message fowarded to Bob" );
        } else {
            if( outGoingSocket1 == null ) {
                outGoingSocket1 = new Socket( ConstantVariables.IP,
                        ConstantVariables.ALICE_PORT );
                out1 = new ObjectOutputStream(
                        outGoingSocket1.getOutputStream() );
            }
            out1.writeObject( msg );
            System.out.println( "Message fowarded to Alice" );
        }
    }
}